var CryptoJS = require("crypto-js")

function decrypt(data, aes_key) {
    const AESKey = CryptoJS.enc.Latin1.stringify(CryptoJS.enc.Base64.parse(aes_key))
    let IV = AESKey.slice(0, 16)
    const CBCOptions = {
        iv: CryptoJS.enc.Latin1.parse(IV),
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    }
    const key = CryptoJS.enc.Latin1.parse(AESKey)
    const decrypt = CryptoJS.AES.decrypt(data, key, CBCOptions);
    var ddMsgStr = CryptoJS.enc.Latin1.stringify(decrypt).toString();
    return JSON.parse(ddMsgStr.substring(20, ddMsgStr.lastIndexOf('}') + 1))
}

function encrypt(data, aes_key) {
    const AESKey = CryptoJS.enc.Latin1.stringify(CryptoJS.enc.Base64.parse(aes_key))
    let IV = AESKey.slice(0, 16)
    var CBCOptions = {
        iv: CryptoJS.enc.Latin1.parse(IV),
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    }
    var secretData = CryptoJS.enc.Latin1.parse(data);
    const key = CryptoJS.enc.Latin1.parse(AESKey)
    var encrypted = CryptoJS.AES.encrypt(secretData, key, CBCOptions);
    return encrypted.toString();
}
module.exports = {
    playload: {},
    aes_key: "4Onx2GcTtkctAMHnsPvfT0uF5nufD11YcK1v9GH42mT",
    token: "40GluwpjscauXOhXfCUb2OgKBa1yeBPhAcd",
    AppKey: "dingyofyqnjhyvcvyjwd",
    init: function(aes_key, token, AppKey) {
        this.aes_key = aes_key
        this.token = token
        this.AppKey = AppKey
    },
    test: function() {
        return this.playload;
    },
    returnSuccess: function() {
        const msg = 'success'
        const msg_len = msg.length
        //16位随机数
        const x16 = new Array(16).fill('x')
        const randomString = x16.join().replace(/,/g, '').replace(/[x]/g, function() {
            let r = Math.floor(Math.random() * 16)
            return r.toString(16);
        });
        // 将明文长度转化成32位二进制数字,注意不能写成'0007',这样会被转化成ascll码
        const lengthString = String.fromCharCode(0) + String.fromCharCode(0) + String.fromCharCode(0) + String.fromCharCode(msg_len)
        const $key = this.AppKey
        //构造的回复明文
        //回复钉钉的格式为:msg_encrypt = Base64_Encode( AES_Encrypt[random(16B) + msg_len(4B) + msg + $key] ), 下面是构造过程
        const preMsg = randomString + lengthString + msg + $key
        //加密数据
        const base64encryptedData = encrypt(preMsg, this.aes_key)
        // 后端时间戳是10位,精确到s, 前端为13位,精确到ms
        const localTimestamp = "" + parseInt(new Date() / 1000)
        //每次生成随机数,用于加盐,每次签名会因此而不同
        const localNonce = Math.floor(Math.random() * 100000 + 100000) + ''
        // token要与在开发者平台设置的一致
        const sortLists = [localTimestamp, localNonce, base64encryptedData, this.token];
        sortLists.sort();
        //在本地生成签名,钉钉会进行校验
        let local_msg_str = '';
        for (let text of sortLists) {
            local_msg_str += text;
        }
        const local_msg_signatures = CryptoJS.SHA1(local_msg_str).toString()
        //回复给钉钉的数据
        return {
            timeStamp: localTimestamp,
            msg_signature: local_msg_signatures,
            encrypt: base64encryptedData,
            nonce: localNonce,
        }
    },
    trigger: function(playload) {
        // console.error("playload ===>>> %j", playload)
        var result = decrypt(JSON.parse(playload.body).encrypt, this.aes_key)
        this.playload = result;
        return this.returnSuccess()
    }
}